#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "list.h"
#include "hlog.h"

struct wm_list
{
    xcb_window_t frame;
    xcb_window_t win;
    struct wm_list *prev;
    struct wm_list *next;
};

static wm_list_t *wms_head = NULL;
static wm_list_t *wms_tail = NULL;

static int init_wm_list(xcb_window_t frame, xcb_window_t win)
{
    if (wms_head != NULL) {
        return 0;
    }
    wms_head = (wm_list_t *)calloc(1, sizeof(wm_list_t));
    if (wms_head==NULL) {
        hlog("Calloc wm_list_t failed: %s\n", strerror(errno));
        return -1;
    }
    wms_tail = wms_head;
    wms_head->frame = frame;
    wms_head->win = win;

    return 0;
}

int add_wm_pair(xcb_window_t frame, xcb_window_t win) 
{
    wm_list_t *elem;
    if (wms_head == NULL)
    {
        return init_wm_list(frame,  win);
    }
    elem = (wm_list_t *)calloc(1, sizeof(wm_list_t));
    if (elem==NULL) {
        hlog("Calloc wm_list_t failed: %s\n", strerror(errno));
        return -1;
    } else {
        elem->frame = frame;
        elem->win = win;
    }

    elem->next = wms_head;
    wms_head->prev = elem;
    wms_head = elem;

    return 0;
}

xcb_window_t get_win_by_frame(xcb_window_t frame)
{
    wm_list_t *tmp = wms_head;

    while(tmp!=NULL) {
        if (tmp->frame==frame) {
            return tmp->win;
        }
        tmp = tmp->next;
    }

    return 0;
}

xcb_window_t get_frame_by_win(xcb_window_t win)
{
    wm_list_t *tmp = wms_head;

    while (tmp != NULL)
    {
        if (tmp->win == win)
        {
            return tmp->frame;
        }
        tmp = tmp->next;
    }

    return 0;
}

int delete_by_frame(xcb_window_t frame)
{
    wm_list_t *tmp = wms_tail;
    char is_find = 0;
    while (tmp != wms_head)
    {
        if (tmp->frame==frame) {
            tmp->prev->next = tmp->next;
            tmp->next->prev = tmp->prev;
            tmp->next = NULL;
            tmp->prev = NULL;
            free(tmp);
            tmp = NULL;
            is_find = 1;
            return 0;
        }
        tmp = tmp->prev;
    }
    if (!is_find) {
        if (wms_head->frame!=frame) {
            return -1;
        } else {
            wms_head->next->prev = NULL;
            wms_head = wms_head->next;
            tmp->next = NULL;
            free(tmp);
            tmp = NULL;
        }
    }
    return 0;
}

int delete_by_win(xcb_window_t win)
{
    wm_list_t *tmp = wms_tail;
    char is_find = 0;
    while (tmp != wms_head)
    {
        if (tmp->win == win)
        {
            tmp->prev->next = tmp->next;
            tmp->next->prev = tmp->prev;
            tmp->next = NULL;
            tmp->prev = NULL;
            free(tmp);
            tmp = NULL;
            is_find = 1;
            return 0;
        }
        tmp = tmp->prev;
    }
    if (!is_find)
    {
        if (wms_head->win != win)
        {
            return -1;
        }
        else
        {
            wms_head->next->prev = NULL;
            wms_head = wms_head->next;
            tmp->next = NULL;
            free(tmp);
            tmp = NULL;
        }
    }
    return 0;
}

void destroy_wms_list()
{
    wm_list_t *tmp = wms_head;

    while (wms_head!=NULL) {
        tmp = wms_head;
        wms_head = wms_head->next;
        tmp->prev = NULL;
        tmp->next = NULL;
        free(tmp);
        tmp = NULL;
    }
    wms_tail = NULL;
}